/* @author: 	 Jeramie Hallyburton
 * @file:		 SpaceInvadersView.java
 * @date:		 12/09/2011
 * @description: renders all game elements to the screen
 */
package mobiledev.project3.spaceinvaders;

import java.text.DecimalFormat;

import game.spaceinvaders.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class SpaceInvadersView extends SurfaceView implements
  SurfaceHolder.Callback {
	
	private static final String TAG = SpaceInvadersView.class.getSimpleName();
	private GameLoop loopThread; //loop for controlling the updating/rendering cycle
	private Game game;			//game object for holding the state of the game

	
	//screen variables
	private int screenHeight = 0;
	private int screenWidth = 0;
	private int rightBlock = 0;
	
	//screen elements
	private Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
	private Button fireButton = new Button( BitmapFactory.decodeResource(getResources(), R.drawable.button ), 0, 0 );
	
	//tracking for how long to animate a scene
	private long 	timer = 0;
	private long 	timerDiff = 0;
	boolean 		begin = true;
	
	
		
	//paint color
	private Paint textColor = new Paint();
	private boolean gameOver;
	
	public SpaceInvadersView(Context context) {
		super(context);
		this.game = (Game) context;
		
		// add to intercept events
		getHolder().addCallback(this);
		
		textColor.setColor( Color.WHITE );
		textColor.setTextSize( 25.0f );

		// focusable to handle event
		setFocusable(true);
	 }
	
	
	 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		 int index = 0;
		 
		 //position elements on screen
		 for( Cannon cannon : game.cannons ) {
			 cannon.setY( height - 10 );
			 cannon.setX( ( width / 2 ) - ( index++ * cannon.getBitmap().getWidth() ) );
		 }

		 screenHeight = height;
		 screenWidth = width;
		 
		 game.setScreenHeight( height );
		 game.setScreenWidth( width );
		 
		 rightBlock = (int) (screenWidth - ( screenWidth * 0.2 ));
		 
		 fireButton.setX( (int) (rightBlock + rightBlock * 0.10) );
		 fireButton.setY( screenHeight - fireButton.getBitmap().getHeight() / 2 );
	 }

	 public void surfaceCreated(SurfaceHolder holder) {
		//create animation loop thread
		loopThread = new GameLoop( getHolder(), this );
		loopThread.setRunning( true );
		loopThread.start();
	 }
	 
	 public void surfaceDestroyed(SurfaceHolder holder) {
		 Log.d( TAG, "Surface destroyed" );
		 boolean retry = true;
		 while( retry ) {
			 try {
				 loopThread.setRunning( false );
				 loopThread.join();
				 loopThread = null;
				 retry = false;
			 } catch( InterruptedException ex ) {
				 //try to shut down again
			 }
		 }
		 Log.d( TAG, "Thread successfully destroyed" );
	 }
	
	 @Override
	 public boolean onTouchEvent(MotionEvent event) {
		 if (event.getAction() == MotionEvent.ACTION_DOWN) {
			 //delegate event handling to the sprite
			 //cannon.handleActionDown( (int)event.getX(), (int)event.getY() );
			 fireButton.handleActionDown( (int)event.getX(), (int)event.getY() );

		 } if (event.getAction() == MotionEvent.ACTION_MOVE) {
			 	//can only be dragged in bottom 20% of screen
			 	if( (int)event.getY() >= screenHeight - ( screenHeight * 0.1 ) ) {
			 		//can only be dragged to far right border
			 		if( (int)event.getX() + game.cannons.get(0).getBitmap().getWidth() / 2 <= rightBlock ) {
				 		int index = 0;
				 		for( Cannon cannon : game.getCannons() )
				 			cannon.setX( (int)event.getX() - index++ * cannon.getBitmap().getWidth() );
			 		}
			 	}
			 	
		 } if (event.getAction() == MotionEvent.ACTION_UP) {
			 if( fireButton.isTouched() ) {
				 fireButton.setTouched( false );
				 fireButton.update();
				 game.attemptShot();
			 }
		 }
		 return true;
	 }
	
	 public void render(Canvas canvas) {
		 //repaint the screen black
		 canvas.drawColor( Color.BLACK );
		 
		 		 
		 if( game.isNewLevel() ) {
			 //begin animation
			 if( begin ) {
				 timer = System.currentTimeMillis();
				 begin = false;
			 }

			 //draw pre-level text for 9 seconds
			 timerDiff = System.currentTimeMillis() - timer;
			 
			 if( timerDiff < 9000) {
				 if( game.getCurrentLevel() == 1 ) {
					 canvas.drawText( "Level: " + game.getCurrentLevel(), screenWidth / 2 - 50, screenHeight / 2, textColor );
				 } else {
					 if( timerDiff < 6000 ) {
						 double shots = game.getTotalShots();
						 double hits = game.getHits();
						 DecimalFormat format = new DecimalFormat( "0.00" );
						 double accuracy = 0.0;
						 try {
							 accuracy = ( hits / shots ) * 100.0 ;
						 } catch( Exception e ) {
							 
						 }
						 
						 canvas.drawText( "Shots Fired: " + shots, screenWidth / 2 - 90, (float) (screenHeight / 2.6), textColor );
						 canvas.drawText( "Enemies Destroyed: " + hits, screenWidth / 2 - 140, (float) (screenHeight / 2.25), textColor );
						 canvas.drawText( "Accuracy: " + format.format( accuracy ) + "%", screenWidth / 2 - 100, screenHeight / 2, textColor );
					 } else {
						 game.setTotalShots(0);
						 game.setHits(0);
						 canvas.drawText( "Level: " + game.getCurrentLevel(), screenWidth / 2 - 50, screenHeight / 2, textColor );
					 }
				 }
				 
			 }
			 
			 
			 if( timerDiff > 9000 ) {
				 game.setNewLevel(false);
				 begin = true;
			 }
		 } else if( gameOver ){
			//begin animation
			 if( begin ) {
				 timer = System.currentTimeMillis();
				 begin = false;
			 }
			 
			//draw game over for 8
			 timerDiff = System.currentTimeMillis() - timer;
			 canvas.drawText( "Game Over. ", screenWidth / 2 - 90, (float) (screenHeight / 2.6), textColor );
			 
		 }
		 else {
			//draw background
			 canvas.drawBitmap( background, (float) (0 - screenWidth * 0.35), 0, null );
			 
			 //draw the ships
			 for( Sprite ship : game.ships ) {
				 ship.draw( canvas );
			 }
			 
			 //draw the shots fired
			 for( Shot shot : game.shotsFired ) {
				 shot.draw( canvas );
			 }
			 
			 //draw the cannon
			 for( Cannon cannon : game.cannons )
				 cannon.draw( canvas );
			 
			 //draw right block border
			 canvas.drawLine( rightBlock, 0, rightBlock, screenHeight, textColor );
			 
			 //draw the score
			 canvas.drawText( "Score: ", (float) (rightBlock * 1.05), 50.0f, textColor );
			 canvas.drawText( " " + game.getScore(), (float) (rightBlock * 1.05), 80.0f, textColor );
			 
			 //draw the firebutton
			 fireButton.draw( canvas );
		 }
	 }
	 
	 public void update() {
		 boolean switchDirection = false;
		 
		//update shots fired
		 for( Shot shot : game.shotsFired ) {
			 shot.update();
			 
			 //remove shot if it goes off screen
			 if( shot.getY() < -10 ) {
				 game.shotsFired.remove( shot );
			 } else {
				 game.collisionCheck( shot );
			 }
		 }
		 
		 for( Sprite ship : game.ships ) {
			 //check left or right wall collision
			 if( ( ship.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT 
					 && ship.getX() + ship.getBitmap().getWidth() / 2 >= rightBlock )
					 || ( ship.getSpeed().getxDirection() == Speed.DIRECTION_LEFT 
							 && ship.getX() - ship.getBitmap().getWidth() / 2 <= 0 ) ) {
				 switchDirection = true;
				 ship.update();
				 break;
			 }
			 
			 ship.update();
		 }
		 
		 if( switchDirection ) {
			 for( Sprite ship : game.ships ) {
				//switch directions when colliding with wall
				 ship.getSpeed().toggleXDirection();
				 
				//move down when hits wall
				 ship.setY( ship.getY() + 20 );
				 
				 ship.update();
			 }
		 }
		 
		 //check how many ships are left to determine speed
		 game.checkRemainingShips();
		 
		 game.checkNewLevel();
		 
		 gameOver = game.checkGameOver();
		  
		 for( Cannon cannon : game.cannons )
			 cannon.update();
	 }
}
